﻿using System.Text.Json;
using Core.Authorization;
using Core.Domain.Entities;
using Core.Domain.Enums;
using Core.Domain.ValueObjects;
using Core.Identity.Common.Interfaces.Common.Interfaces;
using Core.Identity.Menus.Dtos;
using Core.Interfaces.Users;
using Core.Persistence;
using Finbuckle.MultiTenant.Abstractions;
using Infrastructure.Tenant;
using Microsoft.Extensions.Logging;

namespace Infrastructure.Persistence;

public class IdentityDbInitializer(
    ILogger<IdentityDbInitializer> logger,
    IIdentityDbContext context,
    IMultiTenantContextAccessor<BoilerplateTenantInfo> multiTenantContextAccessor) : IDbInitializer
{
    public Task MigrateAsync(CancellationToken cancellationToken)
    {
        throw new NotImplementedException();
    }

    public async Task SeedAsync(CancellationToken cancellationToken = default)
    {
        await Task.Run(() => {
            SeedData(context);
            logger.LogInformation("初始化系统数据完成");
        });
    }
    private void SeedData(IIdentityDbContext dbContext)
    {
        if (dbContext.Users.Any()) return;

        var time = DateTimeOffset.UtcNow;
        var adminUserName = multiTenantContextAccessor.MultiTenantContext.TenantInfo?.Id!;
        adminUserName = adminUserName == TenantConstants.Root.Id ? TenantConstants.Root.Id : adminUserName;
        var email = multiTenantContextAccessor.MultiTenantContext.TenantInfo?.AdminEmail;

        var admin = User.Create(
            username: adminUserName,
            password: "123456",
            email: email);
        admin.SetSuperAdmin(true);
        if (adminUserName == TenantConstants.Root.Id)
        {
            admin.SetPhoneNumber("18211338136", true);
        }
        admin.SetGender(GenderType.Male);
        admin.SetEnabled(true);
        admin.SetDescription("系统初始化账号");
        admin.ChangeNickname("系统超级管理员");
        admin.Created = time;
        dbContext.Users.Add(admin);

        var role = Role.Create("SuperAdmin", "超级管理员", "拥有系统所有权限");
        role.Created = time;
        dbContext.Roles.AddRange(role);

        var userRole = UserRole.Create(admin.Id, role.Id);
        userRole.Created = time;
        userRole.CreatedBy = admin.Id;
        userRole.CreatedByName = admin.Username;
        dbContext.UserRoles.Add(userRole);

        if (adminUserName != TenantConstants.Root.Id)
        {
            dbContext.SaveChanges();
            return;
        }

        // 1️⃣ 读取 JSON 文件
        var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "menus.json");

        var json = File.ReadAllText(filePath);

        // 1️⃣ 反序列化原始数据
        var menuDtos = JsonSerializer.Deserialize<List<MenuDto>>(json, new JsonSerializerOptions
        {
            PropertyNameCaseInsensitive = true
        });

        // 初始化数据的时候判断是否是默认租户
        var isRootAdminUser = adminUserName == TenantConstants.Root.Id;
        if (!isRootAdminUser)
        {
            menuDtos = menuDtos?.Where(x => x.Scope == PermissionScope.Tenant).ToList();
        }

        // 2️⃣ 创建字典：记录旧 Id 到新 Id 的映射
        var idMap = new Dictionary<Guid, Guid>();

        // 3️⃣ 第一次遍历：为每条记录生成新 Id，并建立映射
        foreach (var item in menuDtos!)
        {
            var oldId = item.Id;
            var newId = Guid.CreateVersion7(DateTimeOffset.UtcNow); // 或使用雪花算法等分布式 ID
            idMap[oldId] = newId;
            item.Id = newId; // 更新自身 Id
        }

        // 4️⃣ 第二次遍历：更新 ParentId，根据映射关系找到新的父级 Id
        foreach (var item in menuDtos)
        {
            if (item.ParentId.HasValue && idMap.TryGetValue(item.ParentId.Value, out var newParentId))
            {
                item.ParentId = newParentId;
            }
        }

        var menus = new List<Permission>();
        foreach (var item in menuDtos!)
        {
            var meta = new MenuMeta(
                menuType: item.MenuType!.Value,
                title: item.Title,
                name: item.RouteName,
                path: item.Path,
                component: item.Component,
                rank: item.Rank!.Value,
                redirect: item.Redirect,
                icon: item.Icon,
                extraIcon: item.ExtraIcon,
                enterTransition: item.EnterTransition,
                leaveTransition: item.LeaveTransition,
                activePath: item.ActivePath,
                frameSrc: item.FrameSrc,
                frameLoading: item.FrameLoading!.Value,
                keepAlive: item.KeepAlive!.Value,
                hiddenTag: item.HiddenTag!.Value,
                fixedTag: item.FixedTag!.Value,
                showLink: item.ShowLink!.Value,
                showParent: item.ShowParent!.Value);

            var menu = Permission.Create(
                code: item.Code,
                name: item.Name,
                meta: meta,
                parentId: item.ParentId,
                group: item.Group);
            menu.Id = item.Id;
            menu.Description = item.Description;
            menu.Sort = item.Sort;
            menu.Created = time;
            menu.CreatedBy = admin.Id;
            menu.CreatedByName = admin.Username;
            menu.ChangeScope(item.Scope);
            menus.Add(menu);
        }

        dbContext.Permissions.AddRange(menus);

        var rolePermissions = new List<RolePermission>();
        foreach (var menu in menus)
        {
            menu.Created = time;

            var rolePermission = RolePermission.Create(role, menu, AccessState.Allow);
            rolePermission.Created = time;
            rolePermission.CreatedBy = admin.Id;
            rolePermission.CreatedByName = admin.Username;
            rolePermissions.Add(rolePermission);
        }
        dbContext.RolePermissions.AddRange(rolePermissions);
        dbContext.SaveChanges();
    }
}
